﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web.Mvc;
using System.Linq.Expressions;
using System.Web.Routing;
using System.Web.Mvc.Html;

namespace FoundationLib.Web.Mvc
{
	public static class RatingHelper
	{
		public static MvcHtmlString RatingFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> property, 
			IEnumerable<RatingItem> items, RatingStyle styles, object htmlAttributes)
		{
			string propertyName = ExpressionHelper.PropertyPathFor(property);
			object checkedRawValue = property.Compile().Invoke(helper.ViewData.Model);

			int? checkedValue = null;
			if (checkedRawValue is int)
				checkedValue = (int)checkedRawValue;
			else if (checkedRawValue is int?)
				checkedValue = (int?)checkedRawValue;

			if (styles.HasFlag(RatingStyle.Table))
			{
				int cellWidth = (int)Math.Floor(100.0 / items.Count());

				TagBuilder table = new TagBuilder("table");
				table.MergeAttributes(new RouteValueDictionary(htmlAttributes));
				TagBuilder tr1 = new TagBuilder("tr");
				TagBuilder tr2 = new TagBuilder("tr");
				TagBuilder td = new TagBuilder("td");
				td.MergeAttribute("style", String.Format("width: {0}%; text-align: center;", cellWidth));

				foreach (RatingItem item in items)
				{
					td.SetInnerText(item.Name);
					tr1.InnerHtml += td.ToString();

					td.InnerHtml = helper.RadioButtonFor(property, item.Value).ToHtmlString();
					tr2.InnerHtml += td.ToString();
				}
				if (styles.HasFlag(RatingStyle.DisplayNames))
					table.InnerHtml += tr1.ToString();
				table.InnerHtml += tr2.ToString();

				return MvcHtmlString.Create(table.ToString());
			}
			else
			{
				string html = String.Empty;
				TagBuilder div = new TagBuilder("div");
				div.MergeAttributes(new RouteValueDictionary(htmlAttributes));
				div.MergeAttribute("style", "display: inline;");

				foreach (RatingItem item in items)
				{
					html += helper.RadioButtonFor(property, item.Value) + " ";
					if (styles.HasFlag(RatingStyle.DisplayNames))
						html += helper.Encode(item.Name) + " ";
				}

				div.InnerHtml = html;

				return MvcHtmlString.Create(div.ToString());
			}

		}

		public static MvcHtmlString RatingFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> property,
			IEnumerable<RatingItem> items, RatingStyle styles)
		{
			return RatingFor(helper, property, items, styles, null);
		}

		public static MvcHtmlString RatingFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> property,
			IEnumerable<RatingItem> items, bool showHeader, object htmlAttributes)
		{
			RatingStyle style = RatingStyle.Table;
			if (showHeader)
				style |= RatingStyle.DisplayNames;
			return RatingFor(helper, property, items, style, htmlAttributes);
		}

		public static MvcHtmlString RatingFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> property,
			IEnumerable<RatingItem> items, bool showHeader)
		{
			return RatingFor(helper, property, items, showHeader, null);
		}

		public static MvcHtmlString RatingFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> property,
			IEnumerable<RatingItem> items)
		{
			return RatingFor(helper, property, items, true, null);
		}
	}
}
